package com.zhdl.hardware.motor.huichuan.service.impl;

import com.project.common.util.ByteHelper;
import com.zhdl.hardware.callback.CommonCallback;
import com.zhdl.hardware.io.smartLink.service.IOCmdSendService;
import com.zhdl.hardware.motor.huichuan.repository.HcPortCmdHandleDao;
import com.zhdl.hardware.motor.huichuan.service.HCCmdSendService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;

@Slf4j
@Service
public class HCCmdSendServiceImpl implements HCCmdSendService {

    @Resource
    public HcPortCmdHandleDao handleDao;

    @Resource
    public ThreadPoolTaskScheduler taskScheduler1;

    @Resource
    public IOCmdSendService ioCmdSendService;

    Map<String, ScheduledFuture<?>> mapSF = new HashMap<>();

    /**
     * 相对位置下 - different 为 当前位置
     * 绝对模式下 - different 为 0
     *
     * @param slaveId   从站Id
     * @param distance  距离
     * @param different 偏差
     * @param callback  回调函数
     */
    @Override
    public void motorMoveDistance(String port, String slaveId, int distance, int speed, int different, int timeout, CommonCallback<String> callback) {
        handleDao.motorWriteSlagReady(port, slaveId);
        motorSetDistance(port, slaveId, distance);
        motorSetDistance(port, slaveId, speed);
        handleDao.motorWriteSlagRun(port, slaveId);
        String key = "motor" + distance;
        /* 声明循环次数 */
        final int[] times = new int[]{0};
        ScheduledFuture<?> scheduledFuture = taskScheduler1.scheduleWithFixedDelay(() ->
                handleDao.motorReadSlagLocation(port, slaveId, "0B07", bytes ->
                {

                    byte[] mPosition;
                    mPosition = new byte[4];

                    mPosition[2] = bytes[0];
                    mPosition[3] = bytes[1];
                    mPosition[0] = bytes[2];
                    mPosition[1] = bytes[3];

                    String s = ByteHelper.bytesArrayToHexString(mPosition);
                    BigInteger bigInteger = new BigInteger(s, 16);
                    int motorCurrentLocation = bigInteger.intValue();

                    if (motorCurrentLocation >= (distance + different) - 1000
                            && motorCurrentLocation <= (distance + different) + 1000) {
                        callback.statusCallback("0");
                        ScheduledFuture<?> scheduledFuture0 = mapSF.get(key);
                        scheduledFuture0.cancel(false);
                        mapSF.remove(key);
                    } else {
                        /* 超时报警 */
                        times[0]++;
                        if (times[0] > timeout) {
                            ScheduledFuture<?> scheduledFuture0 = mapSF.get(key);
                            scheduledFuture0.cancel(false);
                            mapSF.remove(key);
                            callback.statusCallback("2");
                        }
                        callback.statusCallback("1");
                    }
                }), 100);
        mapSF.put(key, scheduledFuture);
    }

    /**
     * 相对位置下 - different 为 当前位置
     * 绝对模式下 - different 为 0
     *
     * @param slaveId   从站Id
     * @param distance  距离
     * @param different 偏差
     * @param callback  回调函数
     */
    @Override
    public void motorMoveControl(String port, String slaveId, int distance, int speed, int different, int timeout, CommonCallback<String> callback) {
        /* 电机-使能状态 */
        handleDao.motorWriteSlagReady(port, slaveId);
        /* 电机-设置电机移动距离和速度 */
        motorSetDistance(port, slaveId, distance);
        motorSetDistance(port, slaveId, speed);
        /* 开始的时候，先让 Z || P 轴 继电器闭合 io->01 写入 FF00 */
        if ("02".equals(slaveId)) {
            ioCmdSendService.ioWriteCoil05(1, true, s -> {
                log.info("IO-控制继电器闭合");
            });
        } else if ("04".equals(slaveId)) {
            ioCmdSendService.ioWriteCoil05(3, true, s -> {
                log.info("IO-控制继电器闭合");
            });
        } else if ("05".equals(slaveId)) {
            ioCmdSendService.ioWriteCoil05(2, true, s -> {
                log.info("IO-控制继电器闭合");
            });
        } else if ("06".equals(slaveId)) {
            ioCmdSendService.ioWriteCoil05(4, true, s -> {
                log.info("IO-控制继电器闭合");
            });
        }

        /* 电机-电机写入运动 */
        handleDao.motorWriteSlagRun(port, slaveId);

        String key = "motor" + distance;
        /* 声明循环次数 */
        final int[] times = new int[]{0};
        ScheduledFuture<?> scheduledFuture = taskScheduler1.scheduleWithFixedDelay(() ->
                handleDao.motorReadSlagLocation(port, slaveId, "0B07", bytes ->
                {

                    byte[] mPosition;
                    mPosition = new byte[4];

                    mPosition[2] = bytes[0];
                    mPosition[3] = bytes[1];
                    mPosition[0] = bytes[2];
                    mPosition[1] = bytes[3];

                    String s = ByteHelper.bytesArrayToHexString(mPosition);
                    BigInteger bigInteger = new BigInteger(s, 16);
                    int motorCurrentLocation = bigInteger.intValue();

                    if (motorCurrentLocation >= (distance + different) - 1000
                            && motorCurrentLocation <= (distance + different) + 1000) {
                        callback.statusCallback("0");
                        ScheduledFuture<?> scheduledFuture0 = mapSF.get(key);
                        scheduledFuture0.cancel(false);
                        mapSF.remove(key);
                    } else {
                        /* 超时报警 */
                        times[0]++;
                        if (times[0] > timeout) {
                            ScheduledFuture<?> scheduledFuture0 = mapSF.get(key);
                            scheduledFuture0.cancel(false);
                            mapSF.remove(key);
                            callback.statusCallback("2");
                        }
                        callback.statusCallback("1");
                    }
                }), 100);
        mapSF.put(key, scheduledFuture);
    }

    @Override
    public void motorMoveDistance(String port, String slaveId, int distance, int speed, int different, CommonCallback<String> callback) {
        motorMoveDistance(port, slaveId, distance, speed, different, Integer.MAX_VALUE, callback);
    }

    @Override
    public void motorMoveDistance(String port, String slaveId, int distance, int speed, CommonCallback<String> callback) {
        motorMoveDistance(port, slaveId, distance, speed, 0, Integer.MAX_VALUE, callback);
    }

    @Override
    public void motorStatusRun(String port, String slaveId) {
        handleDao.motorWriteSlagRun(port, slaveId);
        log.info("电机：" + slaveId + " 开始运动了!");
    }

    @Override
    public void motorStatusReady(String port, String slaveId) {
        handleDao.motorWriteSlagReady(port, slaveId);
        log.info("电机：" + slaveId + " 变成伺服状态!");
    }

    @Override
    public void motorStatusStop(String port, String slaveId) {
        handleDao.motorWriteSlagStop(port, slaveId);
        log.info("电机：" + slaveId + " 停止运动了!");
    }

    @Override
    public void motorSetDistance(String port, String slaveId, int value) {
        handleDao.writeSlag06(port, slaveId, "110C", value);
        log.info("电机：" + slaveId + " 设置的距离为: " + value);
    }

    @Override
    public void motorSetSpeed(String port, String slaveId, int value) {
        handleDao.writeSlag06(port, slaveId, "110E", value);
        log.info("电机：" + slaveId + " 设置的速度为: " + value);
    }

}
